#include <iostream>
#include <memory>

using std::cout;
using std::endl;
using std::shared_ptr;
using std::weak_ptr;
/*
    当我们使用`shared_ptr`时，它会对所管理的资源进行引用计数跟踪。
    当引用计数减少到0时，`shared_ptr`会自动释放它所管理的资源。
    而`weak_ptr`是一种观察者，它可以观察到一个`shared_ptr`，但是却不会增加引用计数。
    这就意味着当我们通过`weak_ptr`来获取资源时，需要确保资源在获取后不会被意外释放。

    因此，为了确保资源不会在转换后被释放，我们使用`lock`函数尝试将`weak_ptr`转换为`shared_ptr`对象。
    如果转换成功，也就是`weak_ptr`观察的`std::shared_ptr`对象仍然存在，
    那么我们可以通过获取到的`shared_ptr`对象来安全地访问资源。
    如果转换失败，即`weak_ptr`观察的`shared_ptr`对象已经被释放，
    那么获取的`shared_ptr`对象将为空，我们就可以知道资源已经不再可用了。

    使用`lock`函数可以安全地获取`weak_ptr`观察的资源，并且在获取后不必担心资源被意外释放。

    2、怎么查看托管的资源还在不在？
        use_count()是否为0
        lock提升是否成功
        expired()看是否过期
*/
void test(){
    weak_ptr<int> wp;   //因为是观察者，不能初始化
    //块作用域
    {
        shared_ptr<int> sp(new int(10));
        wp=sp;
        cout<<"*sp="<<*sp<<endl;
        //cout<<"*wp="<<*wp<<endl;  不能解引用
        cout<<"sp.use()="<<sp.use_count()<<endl;
        cout<<"wp.use()="<<wp.use_count()<<endl;    //wp不增加引用计数

        cout<<endl;
        shared_ptr<int> sp2=wp.lock();
        //lock函数是weak_ptr类模板提供的一个成员函数，
        //用于尝试将weak_ptr对象转换为shared_ptr对象。
        //在获取资源时需要先将其转换为shared_ptr，以确保资源不会在获取后被释放。
        if(sp2){
            cout<<"提升成功，wp托管的资源还在"<<endl;
            cout<<"*sp2="<<*sp2<<endl;
            cout<<"sp.use()="<<sp.use_count()<<endl;
            cout<<"sp2.use()="<<sp2.use_count()<<endl;
            cout<<"wp.use()="<<wp.use_count()<<endl;
        }
        else
            cout<<"提升失败"<<endl;

        bool flag=wp.expired();
        if(flag){
            cout<<"wp托管空间已不在"<<endl;
        }
        else
            cout<<"托管空间还在"<<endl;
    }

    //离开作用域，sp、sp2没了
    cout<<endl;
    shared_ptr<int> sp2=wp.lock();
    if(sp2){
        cout<<"提升成功，wp托管的资源还在"<<endl;
        cout<<"*sp2="<<*sp2<<endl;
    }
    else
        cout<<"提升失败"<<endl;
        cout<<"wp.use()="<<wp.use_count()<<endl;

    bool flag=wp.expired();
    if(flag){
        cout<<"wp托管空间已不在"<<endl;
    }
    else
        cout<<"托管空间还在"<<endl;
}

int main()
{   
    test();
    return 0;
}

